/*!
  @file conversion.cpp
  @brief Brief description
  @author Kyohei Otsu <kyon@ac.jaxa.jp>
  @date April, 2013
*/

#include "png/libpng_helper.h"
#include "core/core.h"

using namespace std;

namespace png
{

bool PNG::decode(FILE *fp, png_bytep *data)
{
  //-- initailize
  int number_of_passes = -1;

  png_ptr_ = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (!png_ptr_) goto decode_error;

  info_ptr_ = png_create_info_struct(png_ptr_);
  if (!info_ptr_) goto decode_error;

  if (setjmp(png_jmpbuf(png_ptr_))) goto decode_error;
  png_init_io(png_ptr_, fp);
  png_set_sig_bytes(png_ptr_, 8);
  png_read_info(png_ptr_, info_ptr_);

  //-- get meta info
  width_ = png_get_image_width(png_ptr_, info_ptr_);
  height_ = png_get_image_height(png_ptr_, info_ptr_);
  color_type_ = png_get_color_type(png_ptr_, info_ptr_);
  bit_depth_ = png_get_bit_depth(png_ptr_, info_ptr_);
  if (color_type_ == PNG_COLOR_TYPE_RGB) {
    channels_ = 3;
  } else if (color_type_ == PNG_COLOR_TYPE_GRAY) {
    channels_ = 1;
  }

  number_of_passes = png_set_interlace_handling(png_ptr_);
  png_read_update_info(png_ptr_, info_ptr_);

  //-- read file
  if (setjmp(png_jmpbuf(png_ptr_))) goto decode_error;

  allocMemory(height_, width_, channels_);
  png_read_image(png_ptr_, data);

  return 1;

decode_error:
  ERROR("png decode error");
  return 0;
}

bool PNG::encode(png_bytep *data, FILE *fp)
{
  //-- initialize
  png_ptr_ = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if(!png_ptr_) goto encode_error;

  info_ptr_ = png_create_info_struct(png_ptr_);
  if(!info_ptr_) goto encode_error;

  if(setjmp(png_jmpbuf(png_ptr_))) goto encode_error;

  png_init_io(png_ptr_, fp);

  //-- set info
  if(setjmp(png_jmpbuf(png_ptr_))) goto encode_error;

  png_set_IHDR(png_ptr_, info_ptr_, width_, height_,
      bit_depth_, color_type_, PNG_INTERLACE_NONE,
      PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

  png_write_info(png_ptr_, info_ptr_);

  //-- write image
  if(setjmp(png_jmpbuf(png_ptr_))) goto encode_error;
  png_write_image(png_ptr_, data);

  if(setjmp(png_jmpbuf(png_ptr_))) goto encode_error;
  png_write_end(png_ptr_, NULL);

  return 0;

encode_error:
  ERROR("png encode error");
  return 0;
}

} // end of namespace
